package com.kujie.access.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.kujie.access.domain.po.*;
import com.kujie.access.domain.vo.*;
import com.kujie.access.enums.LeaseExpirationWarnEnum;
import com.kujie.access.mapper.*;
import com.kujie.access.service.IHomePageService;
import com.kujie.access.utils.CalculationUtil;
import com.kujie.common.core.utils.DateUtil;
import com.kujie.common.core.utils.reflect.ReflectUtils;
import com.kujie.common.redis.utils.RedisUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.kujie.access.enums.OverdueEnum.*;

/**
 * 首页 api
 *
 * @author check
 * @date 2025-05-27
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class HomePageServiceImpl implements IHomePageService {
    private final PropertyListManagementMapper propertyListManagementMapper;
    private final AccessTenantManagementMapper accessTenantManagementMapper;
    private final CustomerManagementMapper customerManagementMapper;
    private final AccessContractPaymentRecordMapper accessContractPaymentRecordMapper;
    private final ContractManagementMapper contractManagementMapper;
    private final AccessEnterpriseRentalInformationMapper accessEnterpriseRentalInformationMapper;

    @Override
    public RentalSituationVO rentalSituation(String indexCode) {
        RentalSituationVO rentalSituationVO = new RentalSituationVO();


        LambdaQueryWrapper<PropertyListManagement> propertyListManagementLambdaQueryWrapper = new LambdaQueryWrapper<>();
        List<PropertyListManagement> propertyListManagements = queryPropertyListByIndexCode(indexCode, propertyListManagementLambdaQueryWrapper);


        double totalNum = propertyListManagements.size();
        int totalIdleNum = 0;
        for (PropertyListManagement propertyListManagement : propertyListManagements) {
            totalIdleNum = getRentalSituationData(propertyListManagement, rentalSituationVO, totalIdleNum);
        }

        // 总出租率
        rentalSituationVO.setRentRate(CalculationUtil.getPercentage(rentalSituationVO.getSaleNum(), totalNum));

        // 总闲置率
        rentalSituationVO.setIdleRate(CalculationUtil.getPercentage(totalIdleNum, totalNum));

        try {
            ReflectUtils.processDouble(rentalSituationVO);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return rentalSituationVO;
    }

    @Override
    public FinancialIndicatorsVO financialIndicators() {
        FinancialIndicatorsVO financialIndicatorsVO = new FinancialIndicatorsVO();

        LambdaQueryWrapper<AccessContractPaymentRecord> accessContractPaymentRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        accessContractPaymentRecordLambdaQueryWrapper.gt(AccessContractPaymentRecord::getPaymentDeadline, DateUtil.getStartOfYear());
        accessContractPaymentRecordLambdaQueryWrapper.lt(AccessContractPaymentRecord::getPaymentDeadline, DateUtil.getEndOfYear());

        List<AccessContractPaymentRecord> accessContractPaymentRecords = accessContractPaymentRecordMapper.selectList(accessContractPaymentRecordLambdaQueryWrapper);
        Map<String, Double> yearMothToIncome = new HashMap<>();

        for (AccessContractPaymentRecord accessContractPaymentRecord : accessContractPaymentRecords) {
            // 年度累计收入
            financialIndicatorsVO.setTotalIncome(financialIndicatorsVO.getTotalIncome() + Integer.parseInt(accessContractPaymentRecord.getPaymentAmount()));

            if (DateUtil.isCurrentMonth(accessContractPaymentRecord.getPaymentDeadline())) {
                // 当月租金收入
                financialIndicatorsVO.setRentIncome(financialIndicatorsVO.getRentIncome() + Integer.parseInt(accessContractPaymentRecord.getPaymentAmount()));
            }

            // 计算月份
            LocalDateTime paymentDeadline = accessContractPaymentRecord.getPaymentDeadline();

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
            String yearMonth = paymentDeadline.format(formatter);
            yearMothToIncome.put(yearMonth, yearMothToIncome.getOrDefault(yearMonth, 0.0) + Double.parseDouble(accessContractPaymentRecord.getPaymentAmount()));
        }

        // 补全所有月份数据，无则补 0.0
        for (int i = 1; i <= 12; i++) {
            String key = Calendar.getInstance().get(Calendar.YEAR) + "-" + String.format("%02d", i); // 2025-01 ~ 2025-12
            Double monthIncome = yearMothToIncome.getOrDefault(key, 0.0);
            financialIndicatorsVO.getDateList().add(i);
            financialIndicatorsVO.getIncomeList().add(monthIncome);
        }


        // 计算逾期金额
        calcOverdueIncome(financialIndicatorsVO);
        try {
            ReflectUtils.processDouble(financialIndicatorsVO);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return financialIndicatorsVO;
    }

    @Override
    public TenantAnalysisVO tenant() {
        TenantAnalysisVO tenantAnalysisVO = new TenantAnalysisVO();
        List<AccessTenantManagement> accessTenantManagements = accessTenantManagementMapper.selectList();
        Map<String, Integer> tenantIndustryToCount = new HashMap<>();

        // 设置租户总数
        for (AccessTenantManagement accessTenantManagement : accessTenantManagements) {
            statisticTenantMessage(accessTenantManagement, tenantAnalysisVO, tenantIndustryToCount);
        }

        // 租户状态统计
        statisticTenantStatus(tenantAnalysisVO, accessTenantManagements);

        // 统计租户行业分布
        for (Map.Entry<String, Integer> entry : tenantIndustryToCount.entrySet()) {
            statisticTenantIndustry(entry, tenantAnalysisVO);
        }

        try {
            ReflectUtils.processDouble(tenantAnalysisVO);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return tenantAnalysisVO;
    }

    @Override
    public CustomerDynamicsVO customerDynamics() {
        CustomerDynamicsVO customerDynamicsVO = new CustomerDynamicsVO();
        Map<String, Integer> customerIndustryToCount = new HashMap<>();

        // 查询当前月新增的数据
        int newCustomerWithCurrentMonth = customerManagementMapper.selectByDate(DateUtil.getCurrentMonth());


        // 获取客户行业分布
        List<CustomerManagement> customerManagements = customerManagementMapper.selectList();
        for (CustomerManagement customerManagement : customerManagements) {
            if (customerIndustryToCount.containsKey(customerManagement.getCustomerIndustry())) {
                customerIndustryToCount.put(customerManagement.getCustomerIndustry(), customerIndustryToCount.get(customerManagement.getCustomerIndustry()) + 1);
            } else {
                customerIndustryToCount.put(customerManagement.getCustomerIndustry(), 1);
            }
        }

        // 统计客户行业分布
        for (Map.Entry<String, Integer> entry : customerIndustryToCount.entrySet()) {
            statisticCustomerIndustry(entry, customerDynamicsVO);
        }

        customerDynamicsVO.setNewCustomerCount(newCustomerWithCurrentMonth);
        return customerDynamicsVO;
    }

    @Override
    public ContractManageVO contractManage() {
        ContractManageVO contractManageVO = new ContractManageVO();
        List<ContractManagement> contractManagements = contractManagementMapper.selectList();
        for (ContractManagement contractManagement : contractManagements) {

            // 计算正常合同数量
            if ("5".equals(contractManagement.getContractStatus()) && DateUtil.differentDaysByMillisecond(DateUtil.getNowDate(), contractManagement.getContractExpirationDate()) > 30) {
                contractManageVO.setNormalContractCount(contractManageVO.getNormalContractCount() + 1);
            }

            // 计算临期合同数量
            if (DateUtil.differentDaysByMillisecond(DateUtil.getNowDate(), contractManagement.getContractExpirationDate()) <= 30) {
                contractManageVO.setExpiringContractCount(contractManageVO.getExpiringContractCount() + 1);
            }
        }

        // 计算签约率
        contractManageVO.setSigningRate(CalculationUtil.getPercentage(contractManageVO.getNormalContractCount(), contractManagements.size()));
        try {
            ReflectUtils.processDouble(contractManageVO);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return contractManageVO;
    }

    @Override
    public PropertyListSituationVO propertySituation() {
        PropertyListSituationVO propertyListSituationVO = new PropertyListSituationVO();

        // 获取所有房源
        List<PropertyListManagement> propertyListManagements = propertyListManagementMapper.selectList();

        // 按区间统计
        Map<String, Integer> leasedMap = new HashMap<>();
        Map<String, Integer> unLeasedMap = new HashMap<>();

        for (PropertyListManagement propertyListManagement : propertyListManagements) {
            String range = getAreaRange(Double.parseDouble(propertyListManagement.getArea()));
            if ("2".equals(propertyListManagement.getLeaseType())) {
                leasedMap.put(range, leasedMap.getOrDefault(range, 0) + 1);
            } else {
                unLeasedMap.put(range, unLeasedMap.getOrDefault(range, 0) + 1);
            }
        }

        // 补全所有区间
        String[] ranges = {"<100", "100<&", "100<&<300", "300<&"};
        for (String range : ranges) {
            propertyListSituationVO.getPropertySituationVOList().add(new PropertySituationVO(
                range,
                leasedMap.getOrDefault(range, 0),
                unLeasedMap.getOrDefault(range, 0)
            ));
        }
        return propertyListSituationVO;
    }

    @Override
    public List<OverdueStatisticsVO> overdueStatistics() {
        List<AccessTenantManagement> accessTenantManagements = accessTenantManagementMapper.selectList();
        List<String> companyUuids = accessTenantManagements.stream().map(AccessTenantManagement::getCompanyUuid).toList();

        List<AccessEnterpriseRentalInformation> accessEnterpriseRentalInformations = accessEnterpriseRentalInformationMapper
            .selectList(new LambdaQueryWrapper<AccessEnterpriseRentalInformation>().in(!CollectionUtils.isEmpty(companyUuids), AccessEnterpriseRentalInformation::getCompanyUuid, companyUuids));

        // 统计逾期数量
        int withOneMonth = 0;
        int withThreeMonth = 0;
        int overThreeMonth = 0;
        for (AccessEnterpriseRentalInformation accessEnterpriseRentalInformation : accessEnterpriseRentalInformations) {
            if (Objects.isNull(accessEnterpriseRentalInformation.getRentExpirationDate())) {
                continue;
            }
            int overdueDays = DateUtil.differentDaysByLocalDate(accessEnterpriseRentalInformation.getRentExpirationDate(), LocalDate.now());
            if (overdueDays <= 30 && overdueDays > 0) {
                withOneMonth++;
            } else if (overdueDays <= 90 && overdueDays > 0) {
                withThreeMonth++;
            } else if (overdueDays > 90) {
                overThreeMonth++;
            }
        }

        List<OverdueStatisticsVO> overdueStatisticsVOS = new ArrayList<>();
        overdueStatisticsVOS.add(new OverdueStatisticsVO(WITHIN_ONE_MONTH.name(), withOneMonth));
        overdueStatisticsVOS.add(new OverdueStatisticsVO(WITHIN_THREE_MONTHS.name(), withThreeMonth));
        overdueStatisticsVOS.add(new OverdueStatisticsVO(MORE_THAN_THREE_MONTHS.name(), overThreeMonth));
        return overdueStatisticsVOS;
    }

    @Override
    public LeaseExpirationWarnVO leaseExpirationWarn(String code) {
        // 获取redis key
        String redisKey = LeaseExpirationWarnEnum.getByCode(code);

        // 获取缓存数据
        List<EnterpriseRentalInformationVO> result = RedisUtils.getCacheObject(redisKey);

        // 没获取到缓存数据情况处理
        if (result == null) {
            return new LeaseExpirationWarnVO(List.of(), 0);
        }

        return new LeaseExpirationWarnVO(result, result.size());
    }


    private String getAreaRange(double area) {
        if (area < 100) {
            return "<100";
        } else if (area >= 100 && area < 300) {
            return "100<&<300";
        } else if (area >= 300) {
            return "300<&";
        } else {
            return "100<&"; // 匹配 100<=area 但未指定上限的情况
        }
    }

    private void statisticCustomerIndustry(Map.Entry<String, Integer> entry, CustomerDynamicsVO customerDynamicsVO) {
        CustomerIndustryDistributionVO customerIndustryDistributionVO = new CustomerIndustryDistributionVO();
        customerIndustryDistributionVO.setCustomerIndustry(entry.getKey());
        customerIndustryDistributionVO.setCustomerNum(entry.getValue());
        customerDynamicsVO.getCustomerIndustryDistributionVOS().add(customerIndustryDistributionVO);
    }

    private static void statisticTenantStatus(TenantAnalysisVO tenantAnalysisVO, List<AccessTenantManagement> accessTenantManagements) {
        tenantAnalysisVO.setTotalTenantCount(accessTenantManagements.size());
        tenantAnalysisVO.setNormalTenantPercent(CalculationUtil.getPercentage(tenantAnalysisVO.getNormalTenantCount(), tenantAnalysisVO.getTotalTenantCount()));
        tenantAnalysisVO.setOverdueTenantPercent(CalculationUtil.getPercentage(tenantAnalysisVO.getOverdueTenantCount(), tenantAnalysisVO.getTotalTenantCount()));
        tenantAnalysisVO.setExpiringTenantPercent(CalculationUtil.getPercentage(tenantAnalysisVO.getExpiringTenantCount(), tenantAnalysisVO.getTotalTenantCount()));
    }

    private static void statisticTenantIndustry(Map.Entry<String, Integer> entry, TenantAnalysisVO tenantAnalysisVO) {
        TenantIndustryDistributionVO tenantIndustryDistributionVO = new TenantIndustryDistributionVO();
        tenantIndustryDistributionVO.setTenantIndustry(entry.getKey());
        tenantIndustryDistributionVO.setTenantNum(entry.getValue());
        tenantAnalysisVO.getTenantIndustryDistributionVOS().add(tenantIndustryDistributionVO);
    }

    private static void statisticTenantMessage(AccessTenantManagement accessTenantManagement, TenantAnalysisVO tenantAnalysisVO, Map<String, Integer> tenantIndustryToCount) {
//        // 统计正常租户数量
//        if ("1".equals(accessTenantManagement.getLeaseStatus())) {
//            tenantAnalysisVO.setNormalTenantCount(tenantAnalysisVO.getNormalTenantCount() + 1);
//        }
//
//        // 统计逾期租户数量
//        if ("2".equals(accessTenantManagement.getLeaseStatus())) {
//            tenantAnalysisVO.setOverdueTenantCount(tenantAnalysisVO.getOverdueTenantCount() + 1);
//        }
//
//        // 统计临期租户数量
//        if ("3".equals(accessTenantManagement.getLeaseStatus())) {
//            tenantAnalysisVO.setExpiringTenantCount(tenantAnalysisVO.getExpiringTenantCount() + 1);
//        }
//
//        // 统计租户行业分布
//        if (tenantIndustryToCount.containsKey(accessTenantManagement.getIndustryType())) {
//            tenantIndustryToCount.put(accessTenantManagement.getIndustryType(), tenantIndustryToCount.get(accessTenantManagement.getIndustryType()) + 1);
//        } else {
//            tenantIndustryToCount.put(accessTenantManagement.getIndustryType(), 1);
//        }
    }

    private void calcOverdueIncome(FinancialIndicatorsVO financialIndicatorsVO) {
//        // 获取所有逾期的房间号
//        LambdaQueryWrapper<AccessTenantManagement> accessTenantManagementLambdaQueryWrapper = new LambdaQueryWrapper<>();
//        accessTenantManagementLambdaQueryWrapper.eq(AccessTenantManagement::getLeaseStatus, "2");
//        List<AccessTenantManagement> accessTenantManagements = accessTenantManagementMapper.selectList(accessTenantManagementLambdaQueryWrapper);
//        List<String> rentalRoomNumbers = new ArrayList<>();
//        accessTenantManagements.forEach(e -> {
//            String rentalRoomNumber = e.getRentalRoomNumber();
//            if (rentalRoomNumber.contains(",")) {
//                rentalRoomNumbers.addAll(Arrays.stream(rentalRoomNumber.split(",")).toList());
//            } else {
//                rentalRoomNumbers.add(rentalRoomNumber);
//            }
//        });
//
//        // 查询房间号对应的平方和平方租金
//        List<PropertyListManagement> propertyListManagements;
//        if (!rentalRoomNumbers.isEmpty()) {
//            LambdaQueryWrapper<PropertyListManagement> propertyListManagementLambdaQueryWrapper = new LambdaQueryWrapper<>();
//            propertyListManagementLambdaQueryWrapper.in(PropertyListManagement::getRoomNumber, rentalRoomNumbers);
//            propertyListManagements = propertyListManagementMapper.selectList(propertyListManagementLambdaQueryWrapper);
//        } else {
//            propertyListManagements = List.of();
//        }
//
//        // 计算逾期租金
//        for (PropertyListManagement propertyListManagement : propertyListManagements) {
//            double area = Double.parseDouble(propertyListManagement.getArea());
//            double rent = Double.parseDouble(propertyListManagement.getRent());
//            financialIndicatorsVO.setOverdueIncome(financialIndicatorsVO.getOverdueIncome() + (area * rent));
//        }
    }

    private static int getRentalSituationData(PropertyListManagement propertyListManagement, RentalSituationVO rentalSituationVO, int totalIdleNum) {
        // 可租售总面积
        rentalSituationVO.setTotalArea(rentalSituationVO.getTotalArea() + Double.parseDouble(propertyListManagement.getArea()));

        // 可租总面积和未租套数
        if ("1".equals(propertyListManagement.getLeaseType())) {
            rentalSituationVO.setCanRentArea(rentalSituationVO.getCanRentArea() + Double.parseDouble(propertyListManagement.getArea()));
            rentalSituationVO.setUnSaleNum(rentalSituationVO.getUnSaleNum() + 1);
        }

        // 可售总面积和未售套数
        if ("2".equals(propertyListManagement.getLeaseType())) {
            rentalSituationVO.setCanSaleArea(rentalSituationVO.getCanSaleArea() + Double.parseDouble(propertyListManagement.getArea()));
            rentalSituationVO.setUnRentNum(rentalSituationVO.getUnRentNum() + 1);
        }

        // 已租面积和已租套数
        if ("4".equals(propertyListManagement.getLeaseType())) {
            rentalSituationVO.setRentArea(rentalSituationVO.getRentArea() + Double.parseDouble(propertyListManagement.getArea()));
            rentalSituationVO.setSaleNum(rentalSituationVO.getSaleNum() + 1);
        }

        // 已售面积和已售出套数
        if ("5".equals(propertyListManagement.getLeaseType())) {
            rentalSituationVO.setSaleArea(rentalSituationVO.getSaleArea() + Double.parseDouble(propertyListManagement.getArea()));
            rentalSituationVO.setRentNum(rentalSituationVO.getRentNum() + 1);
        }

        // 空闲面积
        if ("1".equals(propertyListManagement.getLeaseType()) || "2".equals(propertyListManagement.getLeaseType())) {
            rentalSituationVO.setIdleArea(rentalSituationVO.getIdleArea() + Double.parseDouble(propertyListManagement.getArea()));
            totalIdleNum = totalIdleNum + 1;
        }
        return totalIdleNum;
    }

    private List<PropertyListManagement> queryPropertyListByIndexCode(String indexCode, LambdaQueryWrapper<PropertyListManagement> propertyListManagementLambdaQueryWrapper) {
        List<PropertyListManagement> propertyListManagements = List.of();
        if ("root00000".equals(indexCode)) {
            propertyListManagements = propertyListManagementMapper.selectList();
        } else if ("A".equals(indexCode) || "B".equals(indexCode)) {
            propertyListManagementLambdaQueryWrapper.like(PropertyListManagement::getIndexCode, indexCode);
            propertyListManagements = propertyListManagementMapper.selectList(propertyListManagementLambdaQueryWrapper);
        } else {
            propertyListManagementLambdaQueryWrapper.eq(PropertyListManagement::getIndexCode, indexCode);
            propertyListManagements = propertyListManagementMapper.selectList(propertyListManagementLambdaQueryWrapper);
        }

        return propertyListManagements;
    }
}
